March 30, 2021
이번에는 프로젝트하면서 제가 어떻게 리다이렉션 없이 url을 변경했고, 그에따라 모달을 띄워주었는지 소개해보고자 합니다.
해당 문제를 해결 할 때 인스타그램의 웹을 많이 참고했습니다.
일단, 제가 원하는 /search 페이지의 구조는 아래와 같습니다.
여기서 충돌되는 점은 인피니트 스크롤링
과 url의 변경
이었습니다.
이 경우에는 기존에 로딩 되었던 데이터를 유지하는 과정이 추가됩니다. 물론 데이터를 캐싱해놓았고, 스크롤 위치도 저장되기 때문에 해당 과정이 복잡하지는 않지만, 저는 리뷰 리스트에서는 정말 리뷰 데이터가 ‘모달’ 처럼 띄워지는 것을 계획했기 때문에, 새로 페이지를 만들어서 뒷배경(overlay)에 리뷰 리스트를 다시 로딩하여 띄워주는 것은 매우 비효율적이라고 판단했습니다.
이 경우는 유저가 특정 리뷰 페이지의 url을 저장해놓고 나중에 다시 접근할 가능성도 있는데 인피니트 스크롤링 데이터가 사라진 후에 접속하게 되면 해당 리뷰 데이터가 제대로 로딩 되지 않게 됩니다. 즉, 개별 리뷰 페이지의 주소가 부재하게 됩니다.
즉, 사용자가 새로고침을 누르면, 모달창이 닫히고, 개별 리뷰로서의 페이지는 사라지기 때문에 저의 요구사항과는 맞지 않았습니다.
그러면 총 두가지의 문제를 해결해야합니다.
인스타그램이 정확히 어떻게 구현되어있는지는 모르겠지만, 인스타그램을 웹으로 접속하여 개별 포스트를 클릭하면 저의 요구사항과 거의 같게 동작됩니다.
저는 아래와 같은 이유로 인스타그램 역시, 모달 창을 띄웠을 때 리다이렉션 없이 url을 변경하지 않는 방식으로 구현되었다고 판단했습니다
그렇다면 인스타그램처럼 리다이렉션 없이 url을 변경하는 방법을 구현해보겠습니다.
즉, 모달창 오픈과 함께 url을 변경해주어야 하고, 이 때 리다이렉션을 일으키지 않아야합니다.
따라서 기존의 Router는 사용하지 못합니다.
window.history.replaceState
메서드를 통해 가능합니다.window.history.replaceState(null, '', `/search/${postId}`) // 개별 리뷰 url로 가기
window.history.replaceState(null, '', '/search') // 기존 url로 돌아가기
이를 모달 오픈과 클로즈에 적용하면 아래와 같이 구현됩니다.
const openModal = useCallback(
(id: string) => async () => {
window.history.replaceState(null, '', `${routes.POST}/${id}`)
modalHandler()
},
[fullReviews, showModal]
)
const closeModal = useCallback(() => {
window.history.replaceState(null, '', originPath)
modalHandler()
}, [originPath, showModal])
두번째 문제 해결은 간단합니다. /post/[id] 페이지를 생성하고, 해당 페이지에서는 id 파라미터 값에 따라서 리뷰 데이터를 서버 혹은 캐시로부터 가져오면 됩니다.
이렇게 원하는 요구사항을 구현할 수 있었습니다.